#include <iostream>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

static const char *pathName = "/home/lw/code/review";
static const int projID = 825;
static const int shmStandardSize = 4096;
static const int ServerFlag = IPC_CREAT | IPC_EXCL | 0666;
static const int ClientFlag = IPC_CREAT | 0666;

key_t GetKey()
{
    key_t key = ::ftok(pathName, projID);
    if (key < 0)
    {
        std::cout << "create key error\n";
        exit(1);
    }
    return key;
}

int CreatShm(key_t key, int size, int flag)
{
    int shmid = ::shmget(key, size, flag);
    if (shmid < 0)
    {
        std::cout << "create error, alreay exist...\n";
        exit(2);
    }
    std::cout << "create shm success...\n";
    return shmid;
}

int GetShm(key_t key, int size, int flag)
{
    int shmid = ::shmget(key, size, flag);
    if (shmid < 0)
    {
        std::cout << "client get shm error\n";
        exit(3);
    }
    std::cout << "get shm success...\n";
    return shmid;
}

void *ShmAttach(int shmid)
{
    void *addr = ::shmat(shmid, nullptr, 0);
    if (addr == (void *)-1)
    {
        std::cout << "attach fail\n";
        exit(4);
    }
    std::cout << "attach success...\n";
    return addr;
}

void ShmDetach(void *addr)
{
    int n = ::shmdt(addr);
    if (n < 0)
    {
        std::cout << "detach fail\n";
        exit(5);
    }
    std::cout << "detach success\n";
}

void DestroyShm(int shmid)
{
    int n = ::shmctl(shmid, IPC_RMID, nullptr);
    if (n < 0)
    {
        std::cout << "destroy shm error\n";
        exit(6);
    }
    std::cout << "destroy shm success\n";
}

// 共享内存没有同步机制，需要我们自己进行同步
class Sync
{
    const char* fileName = "./test.txt";
public:
    Sync()
    {
        mkfifo(fileName, 0666);
    }
    void Read()
    {
        _fd = open(fileName, O_RDONLY);
    }
    void Write()
    {
        _fd = open(fileName, O_WRONLY);
    }
    int Wait()
    {
        int tmp;
        ssize_t n = read(_fd, &tmp, sizeof(tmp));
        return n;
    }
    void Signal()
    {
        int tmp = 12;
        ssize_t n = write(_fd, &tmp, sizeof(tmp));
    }
    ~Sync()
    {
        unlink(fileName);
    }
private:
    int _fd;
};